package com.ruoyi.activiti.utils;

import org.activiti.bpmn.model.*;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.impl.util.CollectionUtil;
import org.activiti.engine.repository.ProcessDefinition;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Component
public class GatewayConditionService {

    private final RepositoryService repositoryService;

    public GatewayConditionService(RepositoryService repositoryService) {
        this.repositoryService = repositoryService;
    }

    /**
     * 获取网关的所有出线条件表达式
     * @param processDefinitionId 流程定义ID
     * @param gatewayId 网关元素ID
     * @return 序列流ID到条件表达式的映射
     */
    public Map<String, String> getGatewayConditions(String processDefinitionId, String gatewayId) {
        Gateway gateway = getGatewayElement(processDefinitionId, gatewayId);
        return gateway.getOutgoingFlows().stream()
                .collect(Collectors.toMap(
                        SequenceFlow::getId,
                        flow -> flow.getConditionExpression() != null 
                                ? flow.getConditionExpression() 
                                : "无表达式"));
    }

    /**
     * 获取网关的详细条件信息
     * @param processDefinitionId 流程定义ID
     * @param gatewayId 网关元素ID
     * @return 条件信息列表
     */
    public List<SequenceFlowCondition> getSequenceFlowConditions(String processDefinitionId, String gatewayId) {
        Gateway gateway = getGatewayElement(processDefinitionId, gatewayId);
        List<SequenceFlowCondition> conditions = new ArrayList<>();
        
        for (SequenceFlow flow : gateway.getOutgoingFlows()) {
            SequenceFlowCondition condition = new SequenceFlowCondition();
            condition.setId(flow.getId());
            condition.setName(flow.getName());
            condition.setTargetRef(flow.getTargetRef());
            condition.setDefaultFlow(flow.getId().equals(gateway.getDefaultFlow()));
            
            if (flow.getConditionExpression() != null) {
                condition.setExpression(flow.getConditionExpression());
                condition.setExpressionType(flow.getConditionExpression().getClass().getSimpleName());
            }
            
            conditions.add(condition);
        }
        
        return conditions;
    }

    /**
     * 验证网关条件是否有效
     * @param processDefinitionId 流程定义ID
     * @param gatewayId 网关元素ID
     * @return 验证结果
     */
    public GatewayValidationResult validateGatewayConditions(String processDefinitionId, String gatewayId) {
        Gateway gateway = getGatewayElement(processDefinitionId, gatewayId);
        GatewayValidationResult result = new GatewayValidationResult();
        result.setGatewayId(gatewayId);
        result.setGatewayType(gateway.getClass().getSimpleName());
        
        boolean hasConditions = false;
        boolean hasDefault = gateway.getDefaultFlow() != null;
        
        for (SequenceFlow flow : gateway.getOutgoingFlows()) {
            if (flow.getConditionExpression() != null) {
                hasConditions = true;
                result.addConditionedFlow(flow.getId());
            } else {
                result.addUnconditionedFlow(flow.getId());
            }
        }
        
        result.setHasConditions(hasConditions);
        result.setHasDefaultFlow(hasDefault);
        result.setValid(!(hasConditions && !hasDefault && result.getUnconditionedFlows().size() > 0));
        
        return result;
    }

    /**
     * 获取网关元素（内部方法）
     */
    private Gateway getGatewayElement(String processDefinitionId, String gatewayId) {
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
        FlowElement element = bpmnModel.getFlowElement(gatewayId);
        
        if (!(element instanceof Gateway)) {
            throw new IllegalArgumentException("ID 为 " + gatewayId + " 的元素不是网关");
        }
        
        return (Gateway) element;
    }

    // ============== 数据模型类 ==============
    
    public static class SequenceFlowCondition {
        private String id;
        private String name;
        private String targetRef;
        private String expression;
        private String expressionType;
        private boolean defaultFlow;

        // Getters and Setters
        public String getId() { return id; }
        public void setId(String id) { this.id = id; }
        
        public String getName() { return name; }
        public void setName(String name) { this.name = name; }
        
        public String getTargetRef() { return targetRef; }
        public void setTargetRef(String targetRef) { this.targetRef = targetRef; }
        
        public String getExpression() { return expression; }
        public void setExpression(String expression) { this.expression = expression; }
        
        public String getExpressionType() { return expressionType; }
        public void setExpressionType(String expressionType) { this.expressionType = expressionType; }
        
        public boolean isDefaultFlow() { return defaultFlow; }
        public void setDefaultFlow(boolean defaultFlow) { this.defaultFlow = defaultFlow; }
    }

    public static class GatewayValidationResult {
        private String gatewayId;
        private String gatewayType;
        private boolean hasConditions;
        private boolean hasDefaultFlow;
        private boolean valid;
        private List<String> conditionedFlows = new ArrayList<>();
        private List<String> unconditionedFlows = new ArrayList<>();

        // Getters and Setters
        public String getGatewayId() { return gatewayId; }
        public void setGatewayId(String gatewayId) { this.gatewayId = gatewayId; }
        
        public String getGatewayType() { return gatewayType; }
        public void setGatewayType(String gatewayType) { this.gatewayType = gatewayType; }
        
        public boolean isHasConditions() { return hasConditions; }
        public void setHasConditions(boolean hasConditions) { this.hasConditions = hasConditions; }
        
        public boolean isHasDefaultFlow() { return hasDefaultFlow; }
        public void setHasDefaultFlow(boolean hasDefaultFlow) { this.hasDefaultFlow = hasDefaultFlow; }
        
        public boolean isValid() { return valid; }
        public void setValid(boolean valid) { this.valid = valid; }
        
        public List<String> getConditionedFlows() { return conditionedFlows; }
        public void addConditionedFlow(String flowId) { this.conditionedFlows.add(flowId); }
        
        public List<String> getUnconditionedFlows() { return unconditionedFlows; }
        public void addUnconditionedFlow(String flowId) { this.unconditionedFlows.add(flowId); }
    }
}